{% extends 'template/jhTemplateV4.html'%} {% block vueTemplate %}

<!--SQL START
-- 以下为 jianghu init 工具生成的参考 SQL，使用后删除
-- 创建 page
INSERT INTO `_page` (`pageId`,`pageName`,`pageType`,`sort`,`operation`,`operationByUserId`,`operationByUser`,`operationAt`) SELECT 'violationManagement','页面','showInMenu','5','jhInsert',NULL,NULL,NULL FROM DUAL WHERE NOT EXISTS (SELECT `pageId` FROM `_page` WHERE `pageId`='violationManagement');

-- 创建 resource
INSERT INTO `_resource` (`accessControlTable`,`resourceHook`,`pageId`,`actionId`,`desc`,`resourceType`,`appDataSchema`,`resourceData`,`requestDemo`,`responseDemo`,`operation`,`operationByUserId`,`operationByUser`,`operationAt`) SELECT NULL,NULL,'violationManagement','selectItemList','✅查询-查询列表','sql','{}','{ \"table\": \"violation\", \"operation\": \"select\" }','','','insert',NULL,NULL,NULL FROM DUAL WHERE NOT EXISTS (SELECT `pageId` FROM `_resource` WHERE `pageId`='violationManagement' AND `actionId`='selectItemList');
INSERT INTO `_resource` (`accessControlTable`,`resourceHook`,`pageId`,`actionId`,`desc`,`resourceType`,`appDataSchema`,`resourceData`,`requestDemo`,`responseDemo`,`operation`,`operationByUserId`,`operationByUser`,`operationAt`) SELECT NULL,NULL,'violationManagement','insertItem','✅查询-添加成员','sql','{}','{ \"table\": \"violation\", \"operation\": \"insert\" }','','','insert',NULL,NULL,NULL FROM DUAL WHERE NOT EXISTS (SELECT `pageId` FROM `_resource` WHERE `pageId`='violationManagement' AND `actionId`='insertItem');
INSERT INTO `_resource` (`accessControlTable`,`resourceHook`,`pageId`,`actionId`,`desc`,`resourceType`,`appDataSchema`,`resourceData`,`requestDemo`,`responseDemo`,`operation`,`operationByUserId`,`operationByUser`,`operationAt`) SELECT NULL,NULL,'violationManagement','updateItem','✅查询-更新成员','sql','{}','{ \"table\": \"violation\", \"operation\": \"update\" }','','','insert',NULL,NULL,NULL FROM DUAL WHERE NOT EXISTS (SELECT `pageId` FROM `_resource` WHERE `pageId`='violationManagement' AND `actionId`='updateItem');
INSERT INTO `_resource` (`accessControlTable`,`resourceHook`,`pageId`,`actionId`,`desc`,`resourceType`,`appDataSchema`,`resourceData`,`requestDemo`,`responseDemo`,`operation`,`operationByUserId`,`operationByUser`,`operationAt`) SELECT NULL,NULL,'violationManagement','deleteItem','✅查询-删除信息','sql','{}','{ \"table\": \"violation\", \"operation\": \"delete\" }','','','insert',NULL,NULL,NULL FROM DUAL WHERE NOT EXISTS (SELECT `pageId` FROM `_resource` WHERE `pageId`='violationManagement' AND `actionId`='deleteItem');
SQL END!-->

<script id="app-template" type="text/html">
	<div>
		<v-app mobile-breakpoint="sm">
			<jh-menu />
			<v-main class="mt-15">
				<!-- 头部内容 >>>>>>>>>>>>> -->
				<div class="jh-page-second-bar px-8">
					<v-row>
						<v-col cols="12" xs="12" sm="12" md="4" xl="3">
							<div class="pt-3 text-h7 font-weight-bold">
								车辆违章管理
								<!-- 帮助页按钮 -->
								<v-icon @click="isHelpPageDrawerShown = true" color="success" small>
									mdi-help-circle-outline
								</v-icon>
							</div>
							<v-breadcrumbs class="pb-3 pt-0 pl-0" :items="breadcrumbs" divider="-"></v-breadcrumbs>
						</v-col>
						<!-- 搜索条件表单 >>>>>>>> -->
						<v-col cols="12" xs="12" sm="12" md="8" xl="9">
							<v-row class="jh-backend-form-container justify-end ma-0 py-1 pb-xs-2">
								<v-col cols="12" xs="6" sm="6" md="4" xl="3" class="pa-xs-0 pb-2 pl-1 pl-xs-1">
									<v-select
										v-model="serverSearchInput.status"
										color="success"
										prefix="状态："
										class="jh-v-input bg-white"
										:items="constantObj.status"
										dense
										filled
										single-line></v-select>
								</v-col>
								<v-col cols="12" xs="6" sm="6" md="4" xl="3" class="pa-xs-0 pb-2 pl-1 pl-xs-1">
									<v-autocomplete
										clearable
										class="jh-v-input bg-white"
										prefix="车牌号："
										v-model="serverSearchInput.carNumber"
										:items="this.tableData.map(item=>item.carNumber)"
										dense
										filled
										single-line></v-autocomplete>
								</v-col>
								<v-btn
									class="jh-backend-search-btn elevation-0 ml-0 mt-3"
									color="success"
									small
									@click="doUiAction('getTableData')">
									查询
								</v-btn>
							</v-row>
						</v-col>
						<!-- <<<<<<<< 搜索条件表单 -->
					</v-row>
				</div>
				<!-- <<<<<<<<<<<<< 头部内容 -->

				<div class="jh-page-body-container px-8">
					<!-- 页面内容 >>>>>>>>>>>>> -->
					<v-card class="rounded-lg">
						<v-row class="ma-0 pa-4">
							<!-- 新增按钮 -->
							<v-btn color="success" class="elevation-0 mr-2" @click="doUiAction('startCreateItem')" small>
								新增
							</v-btn>
							<v-menu bottom offset-y>
								<template v-slot:activator="{ on, attrs }">
									<v-btn class="elevation-0 mr-2 custom" color="#2196F3" v-bind="attrs" v-on="on" small>
										导出
									</v-btn>
								</template>
								<v-list>
									<v-list-item v-for="(item, i) in exportItems" :key="i" @click="exportData(item.type)">
										<v-list-item-title>{{ item.text }}</v-list-item-title>
									</v-list-item>
								</v-list>
							</v-menu>
							<!-- <v-btn color="success" class="elevation-0 mr-2" @click="exportExcel" small>导出excel</v-btn> -->
							<v-spacer></v-spacer>
							<!-- 搜索过滤 -->
							<v-col cols="12" xs="8" sm="4" md="3" xl="2" class="pa-0">
								<v-text-field
									color="success"
									v-model="searchInput"
									prefix="搜索："
									class="jh-v-input"
									dense
									filled
									single-line></v-text-field>
							</v-col>
						</v-row>
						<!-- 表格 -->
						<v-data-table
							v-model="selectedItem"
							show-select
							:headers="headers"
							:items="tableData"
							:search="searchInput"
							:footer-props="{ itemsPerPageOptions: [20, 50, -1], itemsPerPageText: '每页', itemsPerPageAllText: '所有'}"
							:items-per-page="-1"
							mobile-breakpoint="0"
							:loading="isTableLoading"
							checkbox-color="success"
							:class="{'zebraLine': isTableZebraLineShown }"
							fixed-header
							class="jh-fixed-table-height elevation-0 mt-0 mb-xs-4">
							<template v-slot:item.operationAt="{ item }">{{item.operationAt | dateFormat }}</template>
							<!-- 表格操作按钮 -->
							<template v-slot:item.action="{ item }">
								<span
									role="button"
									class="success--text font-weight-medium font-size-2 mr-2"
									@click="doUiAction('startUpdateItem', item)">
									<v-icon size="16" class="success--text">mdi-note-edit-outline</v-icon>
									修改
								</span>
								<span
									role="button"
									class="success--text font-weight-medium font-size-2 mr-2"
									@click="doUiAction('deleteItem', item)">
									<v-icon size="16" class="success--text">mdi-trash-can-outline</v-icon>
									删除
								</span>
								<span
									role="button"
									class="success--text font-weight-medium font-size-2"
									@click="doUiAction('handleViolationItem', item)"
									v-if="item.status === '待处理'">
									<v-icon size="16" class="success--text">mdi-check-circle-outline</v-icon>
									处理
								</span>
							</template>
							<!-- 没有数据 -->
							<template v-slot:loading>
								<div class="jh-no-data">数据加载中</div>
							</template>
							<template v-slot:no-data>
								<div class="jh-no-data">暂无数据</div>
							</template>
							<template v-slot:no-results>
								<div class="jh-no-data">暂无数据</div>
							</template>
							<!-- 表格分页 -->
							<template v-slot:footer.page-text="pagination">
								<span>{{pagination.pageStart}}-{{pagination.pageStop}}</span>
								<span class="ml-1">共{{pagination.itemsLength}}条</span>
							</template>
						</v-data-table>
					</v-card>
					<!-- 新增抽屉 -->
					<drawer-createViolation
						ref="createViolationDrawer"
						:operationType="'create'"
						@success="doUiAction('getTableData')"></drawer-createViolation>

					<!-- 编辑抽屉 -->
					<drawer-createViolation
						ref="updateViolationDrawer"
						:operationType="'update'"
						@success="doUiAction('getTableData')"></drawer-createViolation>

					<!-- <<<<<<<<<<<<< 页面内容 -->
				</div>

				<!-- 帮助页抽屉 >>>>>>>>>>>>> -->
				<v-navigation-drawer
					v-if="isHelpPageDrawerLoaded"
					v-model="isHelpPageDrawerShown"
					:permanent="isHelpPageDrawerShown"
					fixed
					temporary
					right
					width="80%"
					class="elevation-24">
					<iframe style="border: 0" :src="`/${appInfo.appId}/pageDoc#404.md`" width="100%" height="100%"></iframe>
					<v-btn
						elevation="0"
						color="success"
						fab
						absolute
						top
						left
						small
						tile
						class="drawer-close-float-btn"
						@click="isHelpPageDrawerShown = false">
						<v-icon>mdi-close</v-icon>
					</v-btn>
				</v-navigation-drawer>
				<!-- <<<<<<<<<<<<< 帮助页抽屉 -->
				<!-- 导出字段选择弹框 >>>>>>>>>>>>> -->
				<dialog-selectExcelHeader
					ref="dialogSelectExcelHeader"
					:headers="headers"
					@onData="handleExportCloumn"></dialog-selectExcelHeader>
				<!-- <<<<<<<<<<<<< 导出字段选择弹框 -->
			</v-main>
		</v-app>

		<jh-toast />
		<jh-mask />
		<jh-confirm-dialog />
	</div>
</script>

<div id="app"></div>

{% endblock %} {% block vueScript %} {% include 'common/jianghuJs/fixedTableHeightV4.html' %} {% include
'component/drawer/drawer-createViolation.html' %} {% include 'component/common/carNumberSelect.html' %} {% include
'component/common/excelUtil.html' %} {% include 'component/dialog/dialog-selectExcelHeader.html' %}
<script type="module">
	new Vue({
		el: "#app",
		template: "#app-template",
		vuetify: new Vuetify(),
		data: () => ({
			// 面包屑
			breadcrumbs: [
				{
					text: "首页",
					disabled: true,
				},
				{
					text: "车辆违章管理",
					disabled: true,
				},
			],
			isHelpPageDrawerShown: false,
			isHelpPageDrawerLoaded: false,
			isMobile: window.innerWidth < 500,
			// 表格相关数据
			isTableZebraLineShown: true,
			validationRules: {
				requireRules: [v => !!v || "必填"],
			},
			// 下拉选项
			constantObj: {
				status: ["待处理", "已处理"],
			},
			serverSearchInput: {
				status: "待处理",
			},
			searchInput: null,
			isTableLoading: true,
			tableData: [],
			headers: [
				{
					text: "操作",
					value: "action",
					align: "center",
					sortable: false,
					width: 200,
					class: "fixed",
					cellClass: "fixed",
				},
				{ text: "违章单编号", value: "violationId", width: 120 },
				{ text: "车牌号", value: "carNumber", width: 120 },
				{ text: "车辆编号", value: "carId", width: 120 },
				{ text: "客户编号（用车单位）", value: "customerId", width: 120 },
				{ text: "违章时间", value: "violationTime", width: 120 },
				{ text: "违章地点", value: "violationLocation", width: 120 },
				{ text: "违章项目", value: "violationDescription", width: 120 },
				{ text: "扣分", value: "deductPoint", width: 120 },
				{ text: "罚款", value: "violationFine", width: 120 },
				{ text: "状态", value: "status", width: 120 },
				{ text: "项目负责人", value: "projectLeader", width: 120 },
				{ text: "违章人（司机/单位）", value: "violator", width: 120 },
				{ text: "用车单位", value: "carUsingUnit", width: 120 },
				{ text: "违章人联系电话", value: "violatorPhone", width: 120 },
				{ text: "处理时间", value: "handleDate", width: 120 },
				{ text: "操作者", value: "operationByUser", width: 120 },
				{ text: "操作时间", value: "operationAt", width: 250 },
			],

			isCreateDrawerShown: false,
			createItem: {},
			createActionData: {},
			isUpdateDrawerShown: false,
			updateItem: {},
			updateItemId: null,
			updateActionData: {},
			deleteItem: {},
			deleteItemId: null,
			exportItems: [
				{
					text: "全部导出",
					type: "all",
				},
				{
					text: "按字段导出",
					type: "column",
				},
			],
			selectedItem: [],
		}),
		watch: {
			isHelpPageDrawerShown(val) {
				if (val && !this.isHelpPageDrawerLoaded) {
					this.isHelpPageDrawerLoaded = true;
				}
			},
		},
		async created() {},
		mounted() {
			this.doUiAction("getTableData");
		},
		methods: {
			async doUiAction(uiActionId, uiActionData) {
				switch (uiActionId) {
					case "handleViolationItem":
						await this.confirmUpdateItemDialog();
						await this.handleViolationItem(uiActionData);
						await this.getTableData();
						break;
					case "getTableData":
						await this.getTableData();
						break;
					case "startCreateItem":
						await this.prepareCreateFormData();
						await this.openCreateDrawer();
						break;
					case "startUpdateItem":
						await this.prepareUpdateFormData(uiActionData);
						await this.openUpdateDrawer();
						break;
					case "updateItem":
						await this.prepareUpdateValidate();
						await this.confirmUpdateItemDialog();
						await this.prepareDoUpdateItem();
						await this.doUpdateItem();
						await this.closeUpdateDrawer();
						await this.getTableData();
						break;
					case "deleteItem":
						await this.prepareDeleteFormData(uiActionData);
						await this.confirmDeleteItemDialog();
						await this.prepareDoDeleteItem();
						await this.doDeleteItem();
						await this.clearDeleteItem();
						await this.getTableData();
						break;
					default:
						console.error("[doUiAction] uiActionId not find", { uiActionId });
						break;
				}
			},
			async exportExcel() {
				const params = {
					header: this.headers
						.filter(header => header.text != "操作" && header.text != "操作者" && header.text != "操作时间")
						.map(header => header.text),
					key: this.headers
						.filter(header => header.text != "操作" && header.text != "操作者" && header.text != "操作时间")
						.map(header => header.value),
					data: this.tableData,
					filename: `车辆违章信息表`,
				};
				excelUtil.exportData(params);
			},
			async handleViolationItem(uiActionData) {
				// const dayjs = require("dayjs")
				await window.jhMask.show();
				await window.vtoast.loading("正在处理");
				await window.jianghuAxios({
					data: {
						appData: {
							pageId: "violationManagement",
							actionId: "updateItem",
							actionData: { status: "已处理", handleDate: dayjs().format("YYYY-MM-DD hh:mm:ss") },
							where: { violationId: uiActionData.violationId },
						},
					},
				});
				await window.jhMask.hide();
				await window.vtoast.success("处理成功");
			},
			/**
			 * 获取表格数据
			 */
			async getTableData() {
				this.isTableLoading = true;
				const backendSearchData = _.pickBy(this.serverSearchInput, (fieldValue, fieldKey) => {
					if (fieldValue !== null && fieldValue !== "") {
						return true;
					}
				});
				const rows = (
					await window.jianghuAxios({
						data: {
							appData: {
								pageId: "violationManagement",
								actionId: "selectItemList",
								actionData: {},
								where: backendSearchData,
								orderBy: [{ column: "operationAt", order: "desc" }],
							},
						},
					})
				).data.appData.resultData.rows;
				this.tableData = rows.map(row => {
					row.violationTime = row.violationTime && dayjs(row.violationTime).format("YYYY-MM-DD");
					row.handleDate = row.handleDate && dayjs(row.handleDate).format("YYYY-MM-DD");
					row.operationAt = row.operationAt && dayjs(row.operationAt).format("YYYY-MM-DD hh:mm:ss");
					return row;
				});
				this.isTableLoading = false;
			},
			// ---------- 新增数据 uiAction >>>>>>>>>> --------
			async prepareCreateFormData() {
				this.createItem = {};
			},

			async openCreateDrawer() {
				await this.$refs.createViolationDrawer.doUiAction("open");
			},

			// ---------- <<<<<<<<<<< 新增数据 uiAction ---------
			// ---------- 修改数据 uiAction >>>>>>>>>>>> --------
			async prepareUpdateFormData(funObj) {
				this.updateItem = _.cloneDeep(funObj);
			},

			async openUpdateDrawer() {
				await this.$refs.updateViolationDrawer.doUiAction("open", this.updateItem);
			},

			async prepareUpdateValidate() {
				if (await this.$refs.updateForm.validate()) {
					return true;
				}
				throw new Error("请完善表单信息");
			},

			async confirmUpdateItemDialog() {
				if ((await window.confirmDialog({ title: "修改", content: "确定修改吗？" })) === false) {
					throw new Error("[confirmUpdateItemDialog] 否");
				}
			},

			async prepareDoUpdateItem() {
				const { id, ...data } = this.updateItem;
				this.updateItemId = id;
				this.updateActionData = data;
			},

			async doUpdateItem() {
				await window.jhMask.show();
				await window.vtoast.loading("修改数据");
				await window.jianghuAxios({
					data: {
						appData: {
							pageId: "violationManagement",
							actionId: "updateItem",
							actionData: this.updateActionData,
							where: { id: this.updateItemId },
						},
					},
				});

				await window.jhMask.hide();
				await window.vtoast.success("修改数据成功");
			},

			async closeUpdateDrawer() {
				this.isUpdateDrawerShown = false;
				this.updateItem = {};
				this.updateActionData = null;
				this.updateItemId = null;
			},
			// ---------- <<<<<<<<<<< 修改数据 uiAction ---------
			// ---------- 删除数据 uiAction >>>>>>>>>>>> --------
			async prepareDeleteFormData(funObj) {
				this.deleteItem = _.cloneDeep(funObj);
			},
			async confirmDeleteItemDialog() {
				if ((await window.confirmDialog({ title: "删除", content: "确定删除吗？" })) === false) {
					throw new Error("[confirmDeleteItemDialog] 否");
				}
			},
			async prepareDoDeleteItem() {
				const { id } = this.deleteItem;
				this.deleteItemId = id;
			},
			async doDeleteItem() {
				await window.vtoast.loading("删除数据");
				await window.jianghuAxios({
					data: {
						appData: {
							pageId: "violationManagement",
							actionId: "deleteItem",
							actionData: {},
							where: { id: this.deleteItemId },
						},
					},
				});
				await window.vtoast.success("删除数据成功");
			},
			async clearDeleteItem() {
				this.deleteItem = {};
				this.deleteItemId = null;
			},
			// ---------- <<<<<<<<<<< 删除数据 uiAction ---------
			// ---------- 导出  >>>>>>>>>>> ---------
			async exportData(type) {
				if (
					(await window.confirmDialog({ title: "导出提示", content: "未选择导出的数据默认全部导出，确定导出吗？" })) ===
					false
				) {
					throw new Error("[confirmDeleteItemDialog] 否");
				}
				switch (type) {
					case "all":
						// console.log("selectedItem",this.selectedItem);
						let selectData = [];
						if (this.selectedItem.length == 0) {
							selectData = this.tableData;
						} else {
							selectData = this.selectedItem;
						}
						let params = this.prepareExportParams("all", selectData);
						// debugger
						excelUtil.exportData(params);
						break;
					case "column":
						this.$refs.dialogSelectExcelHeader.doUiAction("open");
						break;
					default:
						console.error("未找到导出类型", type);
				}
			},
			handleExportCloumn(data) {
				let params = this.prepareExportParams(
					"column",
					this.selectedItem.length > 0 ? this.selectedItem : this.tableData,
					data.column
				);
				excelUtil.exportData(params);
			},
			// 准备导出数据的参数
			prepareExportParams(type, data, column) {
				let params = {};
				switch (type) {
					case "all":
						const newHeaders = this.headers.map(h => {
							const hv = h.value;
							// const newHv = _.camelCase(hv);
							return {
								...h,
								value: hv,
							};
						});
						params = {
							header: newHeaders.filter(header => header.text != "操作").map(header => header.text),
							key: newHeaders.filter(header => header.text != "操作").map(header => header.value),
							data,
							filename: `车辆基本信息-${dayjs().format("YYYYMMDDHHmmss")}`,
						};
						break;
					case "column":
						params = {
							header: this.headers
								.filter(header => header.text != "操作" && _.includes(column, header.value))
								.map(header => header.text),
							key: column,
							data,
							filename: `车辆基本信息-${dayjs().format("YYYYMMDDHHmmss")}`,
						};
						break;
				}
				return params;
			},
			// ---------- 导出  >>>>>>>>>>> ---------
		},
	});
</script>

<style scoped="">
	.custom .v-btn__content {
		color: #fff;
	}
</style>
{% endblock %}
